# 日期：2023/10/10
# 作者：甄雨锋
# 邮箱：325938399@qq.com
# 博客：yq2048.cn
# 借鉴文章：https://www.cnblogs.com/7qin/p/17600626.html

import subprocess
import os
from tkinter import *
from tkinter import filedialog

# 缓存文件夹:
cache_path = 'D:/Program Files/adbConnectWifi'
# 缓存文件名称:
cache_file_name = 'adbPath.txt'
# 缓存文件夹路径
cache_file_path = os.path.join(cache_path, cache_file_name)


# 功能项: 通过ADB命令, 获取局域网IP
def get_device_ip():
    # ADB文件路径
    adb_path = ""
    # 执行abd命令返回的内容
    output = ""
    # 局域网IP
    ip_address = ""

    # 如果还没有选择ADB路径, 先去更新ADB路径, 然后终止该函数
    if not os.path.exists(cache_file_path):
        print("提示：请先选择ADB存在的路径")
        return get_adb_path()

    # 从缓存文件, 读取ADB文件路径
    with open(cache_file_path, 'r') as f:
        adb_path = f.read()

    # 切换到adb文件夹目录下
    os.chdir(adb_path)
    # 执行adb命令: 这里可能会出错, 因为可能adb路径设置的不对, 然后无法识别adb命令
    try:
        output = subprocess.check_output("adb shell ip -f inet addr show wlan0", shell=True).decode("utf-8").strip()

        if not output:
            raise ValueError('')
    except Exception as e:
        raise ValueError(
            f'\n - 1.请检查ADB文件路径是否设置正确, 当前设置路径 -> {adb_path}\n - 2.请检查手机是否通过USB插入电脑\n - 3.请确保手机与电脑连接的同一WIFI\n - 4.如果提示more than one device/emulator则代表已连接成功, 请忽略此次错误\n')
        return

    # 截取关键内容: ip
    for line in output.split("\n"):
        if "inet " in line:
            ip_start_idx = line.index("inet ") + 5
            ip_end_idx = line.index("/")
            ip_address = line[ip_start_idx:ip_end_idx]
            break

    subprocess.check_output("adb tcpip 5555", shell=True).decode("utf-8").strip()
    subprocess.check_output(f"adb connect {ip_address}:5555", shell=True).decode("utf-8").strip()
    print(
        f"提示：连接成功(您现在可以将USB拔掉了), 请按照以下步骤运行：\n - 1.打开Hbuilder->运行->运行到手机或模拟器\n - 2.运行到Android App基座\n - 3.请选择{ip_address}:5555项, 并点击运行\n - 4.如未有该设备, 请尝试刷新\n")

    init(is_show_tip=False)


# 功能项: 选择ADB文件路径, 存储到固定的缓存文件中
def get_adb_path():
    # 创建一个根窗口
    root = Tk()
    root.withdraw()  # 隐藏根窗口

    # 弹出文件对话框，选择要操作的文件
    checked_file_path = filedialog.askdirectory(title="选择ADB文件路径")

    # 如果没有选择, 则终止
    if not checked_file_path:
        raise ValueError("您已退出选择ADB路径")

    try:
        # 判断文件是否存在, 不存在则创建
        if not os.path.exists(cache_file_path):
            os.makedirs(cache_path)
        # 存储选择的文件路径
        with open(cache_file_path, 'w') as f:
            f.write(checked_file_path)
            print("成功：已更新缓存文件内容\n")

            init(is_show_tip=False)
    except Exception as e:
        raise ValueError(e)


# 退出
def exit_program():
    return


# 帮助
def help():
    print(""" - 1.请先通过USB数据线让手机与电脑相连, 保险情况下请选择传输文件
 - 2.请将手机设置成开发者默认, 并且打开USB调试
 - 3.如果您未设置ADB路径, 请先输入正确序号, 设置ADB路径
   - 3.1: 您可以在选择Hbuild提供的ADB -> Hbuilder安装目录/plugins/launcher/tools/adbs
 - 4.随后可以输入正确序号, 选择无线调试功能
 - 5.手机重启后请重新运行该工具
    """)

    init(is_show_tip=False)

# 初始化界面
def init(is_show_tip=True):
    # 功能数组
    fun_arr = [
        {"name": "前奏:帮助", "fun": help},
        {"name": "选择ADB路径", "fun": get_adb_path},
        {"name": "开启无线调试", "fun": get_device_ip},
        {"name": "退出选项", "fun": exit_program},
    ]
    # 通过输入序号选项, 选中的功能项
    checked_fun = None

    # 正常执行函数时会提示功能, 后续如果选择的功能不正确则会调用自身函数, 此时调用is_show_tip为False, 则不在提示功能
    if is_show_tip:
        # 提示语
        tips_str = "*************功能列表*************"
        # 拼接字符串
        for fun_item in range(len(fun_arr)):
            tips_str += f'\n{fun_item + 1}:{fun_arr[fun_item]["name"]}'
        tips_str += "\n*********************************\n"

        # 输出提示语
        print(tips_str)

    # 这里可能发生: 输入的不是字符串数字无法被转换成int, 下标越界 -> 如果发生直接调用自身
    try:
        # 获取输入的内容, 将它转换成 int 并-1, 这样就成了数组的下标
        checked_index = int(input('请输入执行的功能序号：')) - 1

        # 如果选择的下标<0, 直接抛出异常(在python中如果提取小于0的数组下标不会报错)
        if checked_index < 0:
            raise ValueError("list index out of range")

        # 从功能数组提取选中的项
        checked_fun = fun_arr[checked_index]

        # 执行函数
        checked_fun["fun"]()
    except Exception as e:
        print(f'错误：{e}\n')
        return init(is_show_tip=False)
    except KeyboardInterrupt:
        pass


if __name__ == '__main__':
    init()
